<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="chrome=1">
  
  <title>initWithString和initWithFormat的区别 - duger | Duger 博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  
    <meta name="author" content="Duger wang">
  
  
    <meta name="description" content="网上看到一篇文章，分析initWithString和initWithFormat的区别，用一下他的用例。
&amp;nbsp;下面是测试代码：NSString&amp;nbsp;* str =[[NSString&amp;nbsp;alloc]&amp;nbsp;initWithString:@”this is from initWithString function”];NSLog(@”this is from [[NSStr">
  
  <meta name="description" content="网上看到一篇文章，分析initWithString和initWithFormat的区别，用一下他的用例。
&nbsp;下面是测试代码：NSString&nbsp;* str =[[NSString&nbsp;alloc]&nbsp;initWithString:@”this is from initWithString function”];NSLog(@”this is from [[NSStr">
<meta property="og:type" content="article">
<meta property="og:title" content="initWithString和initWithFormat的区别 - duger">
<meta property="og:url" content="http://www.autonavi.me/2013/09/06/initWithString和initWithFormat的区别---duger.html">
<meta property="og:site_name" content="Duger 博客">
<meta property="og:description" content="网上看到一篇文章，分析initWithString和initWithFormat的区别，用一下他的用例。
&nbsp;下面是测试代码：NSString&nbsp;* str =[[NSString&nbsp;alloc]&nbsp;initWithString:@”this is from initWithString function”];NSLog(@”this is from [[NSStr">
<meta property="og:image" content="http://counter.cnblogs.com/blog/rss/3305348">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="initWithString和initWithFormat的区别 - duger">
<meta name="twitter:description" content="网上看到一篇文章，分析initWithString和initWithFormat的区别，用一下他的用例。
&nbsp;下面是测试代码：NSString&nbsp;* str =[[NSString&nbsp;alloc]&nbsp;initWithString:@”this is from initWithString function”];NSLog(@”this is from [[NSStr">

  
  
    <link rel="icon" type="image/x-icon" href="/images/favicon.ico">
  
  <link rel="stylesheet" href="/css/style.css" type="text/css">

  <!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
  
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-49504269-3']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
</script>

</head>

<body>
  <div class="wrapper">
    <header id="header">
  <div class="title">
    <h1><a href="/">Duger 博客</a></h1>
    <p><a href="/">iOS小生</a></p>
  </div>
  <nav class="nav">
    <ul>
      
        <li><a href="/">Home</a></li>
      
        <li><a href="/archives">Archives</a></li>
      
        <li><a href="/about">About</a></li>
      
        <li><a href="/atom.xml">RSS</a></li>
      
      
    </ul>
    <div class="clearfix"></div>
  </nav>
  <div class="clearfix"></div>
</header>
    <div class="content"><article class="post">
  <header>
    
      <div class="icon"></div>
      <a href="/2013/09/06/initWithString和initWithFormat的区别---duger.html">
  <time datetime="2013-09-06T06:02:00.000Z">
    2013年 9月 06日
  </time>
</a>
    
    
  
    <h1 class="title">initWithString和initWithFormat的区别 - duger</h1>
  

  </header>
  
  <div class="entry">
    
      <p><span><span>网上看到一篇文章，分析initWithString和initWithFormat的区别，用一下他的用例。</span></span></p>
<div>&nbsp;</div><div>下面是测试代码：</div><div><br><br><span>NSString</span>&nbsp;<span>* str =[[</span><span>NSString</span>&nbsp;<span>alloc</span><span>]</span>&nbsp;<span>initWithString</span><span>:</span>@”this is from initWithString function”<span>];</span><br><br><span>NSLog</span><span>(</span>@”this is from [[NSString alloc] initWithString] m_addr is %ld retainCount is %i”<span>, str, [str</span><span>retainCount</span><span>]);</span><br><br>[str&nbsp;<span>release</span>];<br><br>[str&nbsp;<span>release</span>];<br><br>[str&nbsp;<span>release</span>];<br><br><span>NSLog</span><span>(</span>@”this is from [[NSString alloc] initWithString] m_addr is %ld retainCount is %i”<span>, str, [str</span><span>retainCount</span><span>]);</span><br><br>&nbsp;<br><br><span>str = [[</span><span>NSString</span>&nbsp;<span>alloc</span><span>]</span>&nbsp;<span>initWithFormat</span><span>:</span>@”this is from initWithFormat function”<span>];</span><br><br><span>NSLog</span><span>(</span>@”this is from [[NSString alloc] initWithFormat] m_addr is %ld retainCount is %d”<span>, str, [str</span><span>retainCount</span><span>]);</span><br><br><span><span>&nbsp;</span></span><br></div><br><a id="more"></a><br><span><span>下面是LOG的结果：</span></span><br><div><span>&nbsp;this is from [[NSString alloc] initWithString] m_addr is 12356 retainCount is 2147483647</span></div>

<p>&nbsp;this is from [[NSString alloc] initWithString] m_addr is 12356 retainCount is 2147483647</p>
<p>&nbsp;this is from [[NSString alloc] initWithFormat] m_addr is 82076688 retainCount is 1</p>
<p>&nbsp;</p>
<p>&nbsp;this is from [[NSString alloc] initWithString] m_addr is 12356 retainCount is 2147483647</p>
<p>&nbsp;this is from [[NSString alloc] initWithString] m_addr is 12356 retainCount is 2147483647</p>
<p>&nbsp;this is from [[NSString alloc] initWithFormat] m_addr is 78748112 retainCount is 1</p>
<p>&nbsp;</p>
<p>&nbsp;this is from [[NSString alloc] initWithString] m_addr is 12356 retainCount is 2147483647</p>
<p>&nbsp;this is from [[NSString alloc] initWithString] m_addr is 12356 retainCount is 2147483647</p>
<p>&nbsp;this is from [[NSString alloc] initWithFormat] m_addr is 78777072 retainCount is 1</p>
<p><span>&nbsp;</span></p>
<div>我将上面这段测试代码调用了三次，得到以上的LOG结果。顺便得出这么几条结论。对于不对，请大家鉴定。</div><div>1.从两个变量的地址看，两个变量的地址差据较大。前者的地址非常靠前。</div><div>2.从<span>release</span>看，前者无论被release多少次，都不会被释放，而且的值不变，而后者只要release一次，变量即消亡。</div><div>3.前者的releaseCount=&nbsp;<span>NSIntegerMax</span>,而<span>NSIntegerMax ==</span><span>INT_MAX&nbsp;</span>,而<span>&nbsp;UINT_MAX== (INT_MAX <em>&nbsp;<span>2U</span>&nbsp;+&nbsp;<span>1U</span>)</em></span>。</div><div>U是指无符号整型，而我们默认的int和NSInteger是有符号的，在32位系统中，NSIntegerMax=0X7FFFFFFF，对其乘以2U，即一次向左挪一位。结果为0XFFFFFFFE，再加1U为0XFFFFFFFF，即无符号的最大值。</div><div>然后根据苹果官方对于retainCount方法的描述：</div><div><br><br><strong><span>retainCount</span></strong><br><br>Returns the receiver&rsquo;s reference count. (required)<br><div>- (NSUInteger)retainCount</div><div><br><br><strong>Return Value</strong><br><br>The receiver&rsquo;s reference count.<br></div><div><br><br><em>*Discussion</em><br><br>You might override this method in a class to implement your own reference-counting scheme. For objects that never get released (that is, their&nbsp;<code>[release](file:///Developer/Platforms/iPhoneOS.platform/Developer/Documentation/DocSets/com.apple.adc.documentation.AppleiOS4_2.iOSLibrary.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/release)</code>&nbsp;method does nothing), this method should return&nbsp;<code>UINT_MAX</code>, as defined in&nbsp;<code>&amp;lt;limits.h&amp;gt;</code>.<br><br><span>小生窃以为，此处的UINT_MAX和</span><span>NSIntegerMax是一样的，都是表示所在类型的最大值。所以，initWithString这个方法初始化后的对象是不可能被release的或者说，它的release方法啥也不干。</span><br><br><span style="font-size: large;"><span>验证了上面的分析2.因为他</span></span><span>不可能被release的或者说，它的release方法啥也不干，所以我们调用无数次release都没有起到预先想想的作用。</span><br><br><span style="text-decoration: line-through;">为什么会导致这样的情况呢？</span><br><br><span style="text-decoration: line-through;">我们再次把目光转向地址。眼尖的同学可能会看到initWithString申请的地址每次都是一样的，而initWithFormat的地址每次都不一样，这个说明什么？</span><br><br><span style="text-decoration: line-through;">说明initWithString的地址是静态的，而initWithFormat是动态的。为什么前者是静态的，而后者是动态的？</span><br><br><span style="text-decoration: line-through;">结合上面关于retainCount的分析，小生窃以为initWithString的地址申请是在编译是进行的，这样才能说明为什么它的地址空间如此靠前。只有在编译是进行的，他才是静态的。</span><br><br><span style="text-decoration: line-through;">对于initWithString生成的对象，对其进行dealloc时，程序会报错（这里就不贴LOG了）。而后者initWithFormat不会报错。这进一步验证了initWithString生成的是静态对象，而initWithFormat是动态的。</span><br><br><span style="text-decoration: line-through;">&nbsp;</span><br><br><span style="text-decoration: line-through;">结论：initWithString生成的对象是在编译是申请地址空间，而且在程序中不能释放，不建议使用。（当然也有可能在某种情况下会使用到这个方法，在此不多加讨论）。</span><br></div></div>

<hr>
<p><span style="font-size: 14pt;"><strong>以下解释更为准确：</strong></span></p>
<p><span style="font-size: 16px;">initWithString一个是作为常量字符串，只读数据，</span><br><span style="font-size: 16px;">[[NSString&nbsp;alloc]initWithString:@”this&nbsp;is&nbsp;from&nbsp;initWithString&nbsp;function”];</span><br><span style="font-size: 16px;">这段代码是返回一个不可变对象，而常量字符串本就是不可变，所以这个时候内存会通过isa优化，alloc的区域作废，对象直接指向了”this&nbsp;is&nbsp;from&nbsp;initWithString&nbsp;function”这段常量字符串存储区,作为常量字符串没有retain，所以你retain无数次还是哪个UINR_MAX</span><br><span style="font-size: 16px;">[[NSMutableString&nbsp;alloc]initWithString:@”this&nbsp;is&nbsp;from&nbsp;initWithString&nbsp;function”];</span><br><span style="font-size: 16px;">而这一个是返回一个可变的对象，会另申请空间存放后面的常量字符串，这时其retaincount&nbsp;就为1</span><br><span style="font-size: 16px;">initWithFormat:是一编码格式读入数据，数据存放在哪是根据读入的参数确定的，跟initWithString是右区别的的；</span></p>
<p><span style="font-size: 16px;">[[NSString&nbsp;alloc]initWithFormat:@”dddd”];</span><br><span style="font-size: 16px;">count＝1；</span></p>
<p><span style="font-size: 16px;">[[NSMutableString&nbsp;alloc]&nbsp;initWithFormat:@””];</span><br><span style="font-size: 16px;">count＝1；</span><br><span style="font-size: 16px;">不管返回的是可变和不可变对象，其都会发送一个retain&nbsp;和autoRelease指令</span><br><span style="font-size: 16px;">这两个结果都一样</span></p>
<hr>
<p><span style="font-size: 16px;"><span>&nbsp;</span></span><span style="font-size: 16px;">NSString <em> str1 = [[NSString alloc] initWithString:@”string 1”];</em></span><br><span style="font-size: 16px;">&nbsp;&nbsp;&nbsp;&nbsp;NSLog(@”str1’s address %ld, retain count %d”, (long)str1, [str1 retainCount]);</span><br><span style="font-size: 16px;">&nbsp;&nbsp;&nbsp;&nbsp;NSString  str2 = @”This is string 2”;</span><br><span style="font-size: 16px;">&nbsp;&nbsp;&nbsp;&nbsp;NSLog(@”str2’s address %ld, retain count %d”, (long)str2, [str2 retainCount]);</span><br><span style="font-size: 16px;">&nbsp;&nbsp;&nbsp;&nbsp;NSString * str3 = @”string 1”;</span><br><span style="font-size: 16px;">&nbsp;&nbsp;&nbsp;&nbsp;NSLog(@”str3’s address %ld, retain count %d”, (long)str3, [str3 retainCount]);</span></p>
<p><span style="font-size: 16px;">，运行后输出：</span><br><span style="font-size: 16px;">2011-07-09 21:49:06.526 Ex5_push_pop_nav[1788:207] str1’s address 18176, retain count 2147483647</span><br><span style="font-size: 16px;">2011-07-09 21:49:06.526 Ex5_push_pop_nav[1788:207] str2’s address 18208, retain count 2147483647</span><br><span style="font-size: 16px;">2011-07-09 21:49:06.527 Ex5_push_pop_nav[1788:207] str3’s address 18176, retain count 2147483647</span></p>
<p><span style="font-size: 16px;">可见，str1和str3是在复用内存地址的。或者可以说[[NSString alloc] initWithString:@”string 1”]; 等价于@”string 1”;</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 16px;">所以说只要你代码中写了&nbsp;</span><br><span style="font-size: 16px;">NSString * str3 = @”string 1”;</span><br><span style="font-size: 16px;">实际上就会在程序的静态变量区存在一个值为 &rdquo;string 1”的字符串常量。</span><br><span style="font-size: 16px;">而str3只是指向这个常量。因为这是一个常量，所以它的retainCount是MAX_INT</span><br><span style="font-size: 16px;">多次值为”string 1&ldquo;的变量产生，都会指向这一个常量的地址。</span></p>
<p><span style="font-size: 16px;">如果你把代码写成：</span><br><span style="font-size: 16px;">str = [[NSString alloc] initWithFormat:@”this is from initWithFormat function”];</span><br><span style="font-size: 16px;">实际上是把常量区的复制了一份在堆中，所以你可以release了。但是 @”this is from initWithFormat function” 这个变量本身还是存放在常量区了，所以并没有省内存，反而是增加了内存的使用。</span></p>
<p><span style="font-size: 16px;">所以，如果直接用一个字符串产生另一个字符串，尽量少用 initWithFormat，而不是initWithString。</span></p>
<p><span style="font-size: 16px;">而且，从功能上来说，initWithFormat可以支持 %d 等格式化字串，所以功能更强大一些，但是缺点就是产生了额外的内存空间。</span><br><img src="http://counter.cnblogs.com/blog/rss/3305348" alt=""></p>
<p>本文链接：<a href="http://www.cnblogs.com/duger/p/3305348.html" target="_blank" rel="external">initWithString和initWithFormat的区别</a>，转载请注明。</p>

    
  </div>
  <footer>
    
      
  <div class="categories">
    <a class="categories-link" href="/categories/技术/">技术</a>, <a class="categories-link" href="/categories/技术/iOS/">iOS</a>
  </div>

      
  <div class="tags">
    <a class="tags-link" href="/tags/NSString/">NSString</a>, <a class="tags-link" href="/tags/iOS/">iOS</a>
  </div>

    
    <div class="clearfix"></div>
  </footer>
</article>


<section id="comment">
  <h1 class="title">评论</h1>
  <div class="ds-thread" data-title="initWithString和initWithFormat的区别 - duger">
  </div>
</section>
</div>
  </div>
  <div class="widget-wrapper">
    <aside id="sidebar">
  
  
    
      
      

<div class="widget tag first">
  <h3 class="title">categories</h3>
  <ul class="entry">
  
    <li><a href="/categories/技术/C/">C</a><small>1</small></li>
  
    <li><a href="/categories/技术/Git/">Git</a><small>2</small></li>
  
    <li><a href="/categories/技术/Hexo/">Hexo</a><small>1</small></li>
  
    <li><a href="/categories/技术/iOS/">iOS</a><small>8</small></li>
  
    <li><a href="/categories/只言片语/">只言片语</a><small>2</small></li>
  
    <li><a href="/categories/技术/">技术</a><small>17</small></li>
  
    <li><a href="/categories/随笔/">随笔</a><small>1</small></li>
  
  </ul>
</div>

    
      
      

<div class="widget tagcloud">
  <h3 class="title">标签云</h3>
  <div class="entry">
    <a href="/tags/Apache/" style="font-size: 10.00px;">Apache</a><a href="/tags/C/" style="font-size: 10.00px;">C</a><a href="/tags/Certificates/" style="font-size: 10.00px;">Certificates</a><a href="/tags/ContOS/" style="font-size: 10.00px;">ContOS</a><a href="/tags/Git/" style="font-size: 10.00px;">Git</a><a href="/tags/GitHub/" style="font-size: 10.00px;">GitHub</a><a href="/tags/Google字体/" style="font-size: 10.00px;">Google字体</a><a href="/tags/Jekyll/" style="font-size: 10.00px;">Jekyll</a><a href="/tags/LAMP/" style="font-size: 15.00px;">LAMP</a><a href="/tags/Mac/" style="font-size: 10.00px;">Mac</a><a href="/tags/NSDictionary/" style="font-size: 10.00px;">NSDictionary</a><a href="/tags/NSString/" style="font-size: 10.00px;">NSString</a><a href="/tags/Phabricator/" style="font-size: 10.00px;">Phabricator</a><a href="/tags/Profiles/" style="font-size: 10.00px;">Profiles</a><a href="/tags/SourceTree/" style="font-size: 15.00px;">SourceTree</a><a href="/tags/XCode/" style="font-size: 10.00px;">XCode</a><a href="/tags/Xcode/" style="font-size: 10.00px;">Xcode</a><a href="/tags/code-review/" style="font-size: 10.00px;">code review</a><a href="/tags/delegate/" style="font-size: 10.00px;">delegate</a><a href="/tags/iOS/" style="font-size: 20.00px;">iOS</a><a href="/tags/jekyll/" style="font-size: 10.00px;">jekyll</a><a href="/tags/nil/" style="font-size: 10.00px;">nil</a><a href="/tags/setter/" style="font-size: 10.00px;">setter</a><a href="/tags/人生/" style="font-size: 10.00px;">人生</a><a href="/tags/博客/" style="font-size: 10.00px;">博客</a><a href="/tags/春天/" style="font-size: 10.00px;">春天</a><a href="/tags/苹果证书/" style="font-size: 10.00px;">苹果证书</a>
  </div>
</div>

    
      
      

<div class="widget recent-posts">
  <h3 class="title">最近的文章</h3>
  <ul class="entry">
    
      <li>
        <a href="/2015/08/17/SourceTree中使用BeyondCompare作为默认对比工具.html">SourceTree中使用BeyondCompare作为默认对比工具</a>
      </li>
    
      <li>
        <a href="/2014/09/09/Hexo加载过慢.html">HEXO个人博客速度优化</a>
      </li>
    
      <li>
        <a href="/2014/08/01/hello-world.html">Hello World</a>
      </li>
    
      <li>
        <a href="/2014/04/26/setup-phabricator-on-aliyun.html">在CentOS上搭建Phabricator</a>
      </li>
    
      <li>
        <a href="/2014/04/04/beauly-fade-love-stay.html">Beauly fade Love stay</a>
      </li>
    
  </ul>
</div>

    
  
</aside>
<div class="clearfix"></div>
  </div>
  <footer id="footer"><div class="copyright">
  
  &copy; 2015 <a href="/">Duger wang</a>
  
</div>
<div class="theme-copyright">
  Theme by <a href="https://github.com/orderedlist" target="_blank">orderedlist</a>
   | 
  Redesign by <a href="http://heroicyang.com/" target="_blank">Heroic Yang</a>
</div>
<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span id="busuanzi_container_site_pv">
	本站总访问量<span id="busuanzi_value_site_pv" style="color:white"></span>次
</span>
<div class="clearfix"></div></footer>
  <script src="//ajax.useso.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="/js/scale.fix.js"></script>
<script src="/js/jquery.imagesloaded.min.js"></script>
<script src="/js/gallery.js"></script>


<script type="text/javascript">
  var duoshuoQuery = { short_name: 'duger' };
  (function() {
    var ds = document.createElement('script');
    ds.type = 'text/javascript';
    ds.async = true;
    ds.src = 'http://static.duoshuo.com/embed.js';
    ds.charset = 'UTF-8';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ds);
  })();
</script>



<link rel="stylesheet" href="/fancybox/jquery.fancybox.css" media="screen" type="text/css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
  (function($){
    $('.fancybox').fancybox();
  })(jQuery);
</script>

</body>
</html>